/**
 * Created by AMD on 07.10.14.
 */
package {
import ShopObjects.AbstractGameObjectView;
import ShopObjects.AbstractShelfView;
import ShopObjects.CashDesk1View;
import ShopObjects.HumanView;
import ShopObjects.Shelf1View;

import dragonBones.Armature;
import dragonBones.animation.WorldClock;
import dragonBones.factorys.StarlingFactory;

import feathers.controls.Button;
import feathers.display.Scale9Image;
import feathers.textures.Scale3Textures;
import feathers.textures.Scale9Textures;

import flash.display.Bitmap;

import flash.display.Loader;
import flash.display.LoaderInfo;


import flash.events.Event;
import flash.geom.Matrix;
import flash.geom.Rectangle;
import flash.net.URLRequest;

import starling.display.Image;
import starling.display.QuadBatch;

import starling.display.Sprite;
import starling.filters.BlurFilter;
import starling.filters.ColorMatrixFilter;
import starling.text.BitmapFont;
import starling.text.TextField;
import starling.textures.Texture;
import starling.textures.TextureAtlas;

import treefortress.textureutils.AtlasBuilder;

public class GraphicFactory {
    //atlases
    [Embed(source="/../asset_graphic/atlas_main.png", mimeType="application/octet-stream")]
    private static const _mainAtlas:Class;
    [Embed(source="/../asset_graphic/atlas_interface.png", mimeType="application/octet-stream")]
    private static const _interfaceAtlas:Class;

    //fonts
    [Embed(source="/../asset_graphic/fonts/Nautilus.ttf", embedAsCFF="false", fontFamily="Nautilus")]
    private static const Nautilus:Class;
    //[Embed(source="/../asset_graphic/fonts/ArialRoundedMTProCyr-Bold.otf", embedAsCFF="false", fontFamily="ArialRounded")]
    //private static const ArialRounded:Class;
    [Embed(source="/../asset_graphic/fonts/Debussy.ttf", embedAsCFF="false", fontFamily="Debussy")]
    private static const Debussy:Class;
    [Embed(source="/../asset_graphic/fonts/comicbd.ttf", embedAsCFF="false", fontFamily="ComicBD")]
    private static const ComicBD:Class;
    [Embed(source="/../asset_graphic/fonts/comic.ttf", embedAsCFF="false", fontFamily="Comic")]
    private static const Comic:Class;

    [Embed(source="/../asset_graphic/fonts/ComicDB.fnt", mimeType="application/octet-stream")]
    public static const FontXml:Class;
    //[Embed(source = "/../asset_graphic/fonts/ComicDB.png")]
    //public static const FontTexture:Class;
    [Embed(source="/../asset_graphic/fonts/ComicDB_Dark.fnt", mimeType="application/octet-stream")]
    public static const FontXml2:Class;

    private static var _factory:StarlingFactory = null;
    private static var _completeCallback:Function = null;

    //mac comment

    public static const EVENT_AVATAR_ATLAS_CREATED:String = "EVENT_AVATAR_ATLAS_CREATED";

    public static function init(completeCallback:Function = null):void {
        GraphicFactory._factory = new StarlingFactory();

        GraphicFactory._factory.parseData(new GraphicFactory._mainAtlas())//, "MainAtlas");
        GraphicFactory._factory.parseData(new GraphicFactory._interfaceAtlas())//, "InterfaceAtlas");



        GraphicFactory._completeCallback = completeCallback;
        GraphicFactory._factory.addEventListener(flash.events.Event.COMPLETE, GraphicFactory._onCompleteHandler);
    }

    private static function _onCompleteHandler(event:Event):void {
        GraphicFactory._factory.removeEventListener(flash.events.Event.COMPLETE, GraphicFactory._onCompleteHandler);

        var texture:Texture = (_factory.getTextureDisplay("ComicDB.png") as Image).texture;// Texture.fromEmbeddedAsset(FontTexture);
        var xml:XML = XML(new FontXml());
        var _bitmapFont:BitmapFont = new BitmapFont(texture, xml);
        TextField.registerBitmapFont(_bitmapFont, "ComicDB");

        texture = (_factory.getTextureDisplay("ComicDB_Dark.png") as Image).texture;// Texture.fromEmbeddedAsset(FontTexture);
        xml = XML(new FontXml2());
        _bitmapFont = new BitmapFont(texture, xml);
        TextField.registerBitmapFont(_bitmapFont, "ComicDB_Dark");

        if(GraphicFactory._completeCallback != null){
            GraphicFactory._completeCallback();
        }
    }


    private static var _orangeBtnTexture:Scale9Textures = null;
    public static function createOrangeButton(width:int,height:int,label:String = ""):Button{
        var _button:Button = new Button();

        if(GraphicFactory._orangeBtnTexture == null){
            var _bufImg:Image = GraphicFactory.getImageByName("Interface/OrangeButtonSkin");
            GraphicFactory._orangeBtnTexture = new Scale9Textures(_bufImg.texture,new Rectangle(_bufImg.width/2,_bufImg.height/1.5,1,1));
        }
        var btnImg:Scale9Image = new Scale9Image(GraphicFactory._orangeBtnTexture,1);

        var btnImgHover:Scale9Image = new Scale9Image(GraphicFactory._orangeBtnTexture,1);
        var _filter:ColorMatrixFilter = new ColorMatrixFilter();
        _filter.adjustBrightness(0.2);
        btnImgHover.filter = _filter;

        var btnImgDown:Scale9Image = new Scale9Image(GraphicFactory._orangeBtnTexture,1);
        _filter = new ColorMatrixFilter();
        _filter.adjustBrightness(0.1);
        btnImgDown.filter = _filter;

        _button.defaultSkin =  btnImg;
        _button.hoverSkin = btnImgHover;
        _button.downSkin = btnImgDown;

        _button.width = width;
        _button.height = height;

        var _label:TextField = new TextField(width,height,label,"Nautilus",15,0xFFCD27);

        //_label.filter = BlurFilter.createDropShadow();
        _label.batchable = true;
        //_label.alignPivot();
        _label.autoScale = true;

        if(label.length) _button.addChild(_label)

        _button.useHandCursor = true;

        return _button;
    }



    private static var _scale9TexturesAsset:Object = {};
    public static function getScale9Textures(baseTextureName:String):Scale9Textures {
        if(GraphicFactory._scale9TexturesAsset[baseTextureName] == null){
            var _bufImage:Image = getImageForRender(baseTextureName);
            GraphicFactory._scale9TexturesAsset[baseTextureName] = new Scale9Textures(_bufImage.texture, new Rectangle(_bufImage.width/2,_bufImage.height/2,1,1));
        }
        return GraphicFactory._scale9TexturesAsset[baseTextureName] as Scale9Textures;
    }

    private static var _scale3TexturesAsset:Object = {};
    public static function getScale3Textures(baseTextureName:String):Scale3Textures {
        if(GraphicFactory._scale3TexturesAsset[baseTextureName] == null){
            var _bufImage:Image = getImageForRender(baseTextureName);
            GraphicFactory._scale3TexturesAsset[baseTextureName] = new Scale3Textures(_bufImage.texture, _bufImage.width/2, 1);
        }
        return GraphicFactory._scale3TexturesAsset[baseTextureName] as Scale3Textures;
    }

    public static function getImageByName(name:String):Image{
        return (GraphicFactory._factory.getTextureDisplay(name) as Image);
    }

    private static var _avatarAtlas:TextureAtlas = null;
    private static var _avatarData:Array = null;
    private static var _avatarsLoadCallback:Function = null
    public static function setAvatarData(data:Array, onComplete:Function):void {
        if(onComplete.length != 0){
            throw  new Error("GraphicFactory.as setAvatarData(): parameter onComplete must be a function with no parameters");
        }
        _avatarsLoadCallback = onComplete;
        if(_avatarData == null){
            _avatarData = data;
            _loadNextAvatar();
        }
    }
    private static var _loadedPictures:Array = [];
    private static var loader:Loader;
    private static var _bufInt:int;
    private static function _loadNextAvatar():void {
        if(_loadedPictures.length < _avatarData.length){
            _bufInt = _loadedPictures.length;
            if(_avatarData[_bufInt].picture_url != null && _avatarData[_bufInt].picture_url != ""){
                loader = new Loader();
                loader.contentLoaderInfo.addEventListener(flash.events.Event.COMPLETE, HANDLER_avatarLoadComplete);
                loader.load(new URLRequest(_avatarData[_bufInt].picture_url));
            } else {
                _loadedPictures.push(null); //TODO: add silhouette
                _loadNextAvatar();
            }
        } else {
            _avatarAtlas = _createTextureAtlas(_loadedPictures);
            if(_avatarsLoadCallback != null){
                _avatarsLoadCallback();
            }
        }
    }
    private static function HANDLER_avatarLoadComplete (event:flash.events.Event):void
    {
        loader.contentLoaderInfo.removeEventListener(flash.events.Event.COMPLETE, HANDLER_avatarLoadComplete);
        var _loadedBitmap:Bitmap = new Bitmap(Bitmap(LoaderInfo(event.target).content).bitmapData);
        _loadedBitmap.name = "avatar_"+_loadedPictures.length;
        //trace(_loadedBitmap.name);
        _loadedPictures.push(_loadedBitmap);

        _loadNextAvatar();
    }
    private static function _createTextureAtlas(bitmaps:Array):TextureAtlas {
        var _bitmapsVector:Vector.<Bitmap> = new <Bitmap>[];
        for (var i:int = 0; i < bitmaps.length; i++) {
            if(bitmaps[i] != null){
                _bitmapsVector.push(bitmaps[i] as Bitmap);
            }
        }
        return AtlasBuilder.build(_bitmapsVector);
    }


    public static function getAvatarImageById(id:String):Image {
        for (_bufInt = 0; _bufInt < _avatarData.length; _bufInt++) {
            if(String(_avatarData[_bufInt].id) == id  ){
               return (new Image(_avatarAtlas.getTexture("avatar_"+_bufInt)));
            }
        }
        return null;
    }



    private static var _renderImagesAsset:Object = {}
    ///Возвращает ранее созданное изображение по имени, или создает новое если не использовалось
    public static function getImageForRender(name:String):Image{
        if(GraphicFactory._renderImagesAsset[name] == null){
            GraphicFactory._renderImagesAsset[name] = (GraphicFactory._factory.getTextureDisplay(name) as Image);
        }
        GraphicFactory._renderImagesAsset[name].x = GraphicFactory._renderImagesAsset[name].y = 0;
        return GraphicFactory._renderImagesAsset[name] as Image;
    }


    public static function createHumanArmatureFullFace():Armature {
        var _armature:Armature = GraphicFactory._factory.buildArmature("HumanFull");
        _armature.getBone("Head").childArmature.animation.gotoAndPlay("smile_good");
        return _armature;
    }
    public static function createHumanArmatureHalfFace():Armature {
        var _armature:Armature = GraphicFactory._factory.buildArmature("HumanFullProfile");
        return _armature;
    }


    public static function createHumanView():HumanView {

        return new HumanView();
    }

    public static function createShelfView(model:String):AbstractShelfView {
        var _result:AbstractShelfView;
        switch (model){
            case "1":
                _result = new Shelf1View();
                break;
        }

        return _result;
    }

    public static function createCashDeskView(model:String):AbstractGameObjectView {
        var _result:AbstractGameObjectView;
        switch (model){
            case "1":
                _result = new CashDesk1View();
                break;
        }
        return _result;
    }

    public static function createShelfArmature(shelfModel:int):Armature{
        var _armature:Armature = GraphicFactory._factory.buildArmature("ShopItems/Shelfs/Shelf"+shelfModel);
        return _armature;
    }

    public static function createCashDeskArmature(cashDeskModel:int):Armature{
        if(cashDeskModel == 1){
            var _armature:Armature = GraphicFactory._factory.buildArmature("ShopItems/CashDesks/CashDesk");
        }
        return _armature;
    }

    public static function getTextureDisplay(_textureName:String):Image {
        return (_factory.getTextureDisplay(_textureName) as Image);
    }


    public static function get isReady():Boolean {
        return Boolean(_factory != null);
    }

    public static function get factory():StarlingFactory {
        if(_factory == null){
            throw new Error("GraphicFactory is NOT READY. Use init() function first!");
        }
        return _factory;
    }

    public static function get avatarAtlas():TextureAtlas {
        return _avatarAtlas;
    }
}
}
